
import exception.NoEnoughPapersException;
import strategy.OrderSelectionStrategy;
import strategy.PaperSelectionStrategy;
import strategy.RandomSelectionStrategy;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

// Mutable class 教师发布的一组论文，以及学生选择的结果
public class PaperList {
    private final String teacher; //教师姓名
    private final List<Paper> papers; //该教师发布的论文清单
    private final PaperSelection selections = new PaperSelection(selections);//选择论文结果
    private PaperSelectionStrategy strategy; // 选择策略

    public PaperList(String teacher, List<Paper> papers) {
        this.teacher = teacher;
        this.papers = new ArrayList<>(papers); // 使用防御性拷贝
        this.strategy = new RandomSelectionStrategy(); // 默认随机选择策略
    }

    // 根据论文类型，到 papers 中找出尚未被选择的论文，返回清单。type=Any 意味着任何未被他人
    // 选择的论文都会包含在返回值中
    private List<Paper> getUnselectedPapersByType(PaperType type) {
        List<Paper> results = new ArrayList<>();
        for (Paper p : this.papers) {
            if (!this.selections.isSelected(p)) {
                if (type == PaperType.Any
                        || type.toString().equals(p.getClass().getSimpleName())) {
                    results.add(p);
                }
            }
        }
        return Collections.unmodifiableList(results);
    }

    // 根据学生偏好，为其选择一组论文（结合策略模式）
    public synchronized List<Paper> selectPaperByRandom(Student student) throws NoEnoughPapersException {
        List<Paper> availablePapers = getUnselectedPapersByType(student.getPreferredPaperType());
        int preferredQty = student.getPreferredQuantity();

        // 若可选论文的数量少于学生希望选择的数量，抛出异常
        if (availablePapers.size() < preferredQty) {
            throw new NoEnoughPapersException(student.getName(), preferredQty, availablePapers.size());
        }

        List<Paper> selectedPapers = (List<Paper>) strategy.select(availablePapers, preferredQty);
        for (Paper p : selectedPapers) {
            selections.addSelection(student, p);
        }
        return new ArrayList<>(selectedPapers); // 返回防御性拷贝
    }

    public PaperSelection getSelectionResult() {
        return new PaperSelection(selections); // 返回防御性拷贝
    }

    // 设置选择策略
    public void setStrategy(OrderSelectionStrategy strategy) {
        this.strategy = strategy;
    }
}